package com.lnsoft.cac.server.handle.threadpools;

import com.lnsoft.cac.server.Entity.Command;
import com.lnsoft.cac.server.handle.CACGlobalData;
import com.lnsoft.cac.server.handle.codec.*;
import com.lnsoft.cac.server.handle.codec.frameMessage.*;
import com.lnsoft.cac.server.handle.webservice.MsgHandle.*;
import com.lnsoft.cac.server.handle.webservice.WSClientFactory;
import com.lnsoft.cac.server.util.Arrays16;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelId;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
import org.jdom2.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 业务数据处理线程池
 */
@Component
@Slf4j
public class ServiceInvokePools {

    @Value("${project.is_test}")
    private boolean isTest;

    //  CAG的WebServiceUrl地址
    @Value("${cag.cagWsUrl}")
    private String cagWsUrl;

    @Autowired
    private CACGlobalData cacGlobalData;

    @Autowired
    private DownloadCAGCtrl downloadCAGCtrl;

    @Autowired
    private WSClientFactory wsClientFactory;

    private Client client;

    private volatile boolean flag = false;
    private boolean cagOnline = false;


    private final ExecutorService pools = Executors.newFixedThreadPool(20);


    public void clearPools() {
        pools.shutdown();
    }


    public void executeHandleFrame(final ChannelHandlerContext ctx, final I1Frame i1Frame, final Device device) {
        pools.execute(new Runnable() {
            @Override
            public void run() {

                //  任务一、接收帧报文（或确认报文）、缓存帧报文到全局、发送确认报文.
                try {
                    //  重置超时次数
                    device.setIdleTimeOutNumber(0);
//                    String deviceID = new String(i1Frame.getVoltageMonitorID());
                    String deviceID = device.getClientId();

                    switch (i1Frame.getFrameType()) {
                        case 0x01: {        //  心跳报文帧 （电压监测仪 -> 主发）
                            if (0x01 == i1Frame.getMsgType()) {
                                log.info("{}: <<< HeartBeatFrame", deviceID);

                                //  标记装置的主发状态:打开
                                device.setDeviceSend(1);

                                //  检查是否记录终端编号
                                if (deviceID == null) {
                                    String device_id = new String(i1Frame.getVoltageMonitorID());
                                    device.setClientId(device_id);
                                    deviceID = device_id;
                                    //  检查是否曾经连接过或者存在另一个在线连接
                                    Device d = cacGlobalData.deviceMap4Device.get(device_id);
                                    if (d != null && d.getChannelId() != null) {
                                        CACGlobalData.channelGroup.find(d.getChannelId()).close();
                                    }
                                    //  将最新的连接加入全局
                                    cacGlobalData.deviceMap4Device.put(device_id, device);
                                }

                                //  构造返回帧
                                ByteBuf backFrame = FrameFactory.heartCfmFrame(i1Frame.getVoltageMonitorID(), i1Frame.getFrameSerialNum());

                                //  应答报文数据
                                ctx.writeAndFlush(backFrame);

                                log.info("{}: >>> HeartBeat ConfirmFrame", deviceID);

                                //  更新心跳信息
                                device.setLastHeartBeatTime(System.currentTimeMillis());
                                device.setIdleTimeOutNumber(0);

                                //  标记装置的主发状态:关闭（未占用）
                                device.setDeviceSend(2);

                            } else {
                                log.warn("err: type of HeartBeatFrameContent ; device:{}", deviceID);
                            }

                            break;
                        }
                        case 0x03:   // 监测数据报文（电压监测仪 -> 主发）
                        {
                            switch (i1Frame.getMsgType()) {
                                case 0x04:  // 电压数据报
                                {
                                    log.info("{}: <<< VoltageMinuteData", deviceID);
                                    //  标记装置的主发状态:打开
                                    device.setDeviceSend(1);

                                    @NonNull
                                    Voltage_Msg voltageMsg = Voltage_Msg.decFrameBody(i1Frame.getMsgBody());
                                    log.info("{}: decode VoltageMinuteData", deviceID);


                                    //  构造并返回确认报文
                                    Voltage_Cfm voltage_cfm = new Voltage_Cfm();
                                    voltage_cfm.setMeasure_Point_ID(voltageMsg.getMeasure_Point_ID());
                                    voltage_cfm.setData_Status((byte) 0xFF);

                                    ByteBuf backFrame = FrameFactory.vol_CfmFrame(i1Frame.getVoltageMonitorID(), i1Frame.getFrameSerialNum(), voltage_cfm.toByteBuf());

                                    ctx.writeAndFlush(backFrame);
                                    log.info("{}: >>> VoltageMinuteData ConfirmFrame", deviceID);


                                    if (voltageMsg.getMeasureData_Num() <= 0) {
                                        //  处理数据异常
                                    }

                                    int firstTime = voltageMsg.getMeasureDataList().get(0).getStatTime();
                                    UploadCACData data = new UploadCACData();
                                    data.setMonDataNodeAttr(cacGlobalData.cacDeviceID, Integer.toString(1));
                                    String deviceId = new String(i1Frame.getVoltageMonitorID());
                                    String strMeasurePointNo = Integer.toString(voltageMsg.getMeasure_Point_ID());
                                    String strTimesTamp = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date((long) firstTime * (long) 1000));
                                    for (Voltage_Data item : voltageMsg.getMeasureDataList()) {
                                        int min = BigDecimal.valueOf((long) ((item.getStatTime() - firstTime) / 60)).intValue();
                                        data.addAttrNode("PT" + Integer.toString(min) + "m", Util.voltageBytesToValue(item.getVoltage()));
                                    }

                                    /**
                                     * 检查数据是周期性数据还是召唤数据；
                                     * 周期性数据：加入全局缓存；
                                     * 召唤数据：加入对应指令任务的缓存；
                                     *
                                     * 以下每种帧报文处理类同；
                                     * */
                                    Command cmd = device.getCurrentCmd();
                                    if (cmd != null && cmd.getCmd_type().equals("GETDATA") && cmd.getCmdStatus() == 2) {
                                        data.setDataNodeAttr(deviceId, strMeasurePointNo, "031001", cmd.getCmd_id(), strTimesTamp);

                                        cmd.setCmdResult(data.getMsg());
                                        cmd.setCmdStatus(3);
                                        log.info("{}: buffer VoltageMinuteData", deviceID);
                                    } else {
                                        data.setDataNodeAttr(deviceId, strMeasurePointNo, "031001", null, strTimesTamp);
                                        cacGlobalData.voltageDataXml.add(data.getMsg());
//                                        wsClientFactory.uploadCACData(data.getMsg());
                                    }

                                    log.info(data.getMsg());


                                    //  标记装置的主发状态:关闭（未占用）
                                    device.setDeviceSend(2);
                                    break;
                                }
                                case 0x05:  // 日统计数据报
                                {
                                    log.info("{}: <<< VoltageDayData", deviceID);
                                    //  标记装置的主发状态:打开
                                    device.setDeviceSend(1);

                                    @NonNull
                                    VoltageDayMon_Msg volDayMsg = VoltageDayMon_Msg.decFrameBody(i1Frame.getMsgBody());
                                    log.info("{}: decode voltageDayData", deviceID);
                                    VoltageDayMon_Cfm cfm = new VoltageDayMon_Cfm();
                                    cfm.setMeasure_Point_ID(volDayMsg.getMeasure_Point_ID());
                                    cfm.setData_Status((byte) 0xFF);

                                    ctx.writeAndFlush(FrameFactory.vol_Day_CfmFrame(i1Frame.getVoltageMonitorID(), i1Frame.getFrameSerialNum(), cfm.toByteBuf()));
                                    log.info("{}: >>> VoltageDayData ConfirmFrame", deviceID);

                                    if (volDayMsg.getMeasureData_Num() <= 0) {
                                        //  处理数据异常
                                        log.info("err: type of VoltageDayData FrameContent ; device:{}", deviceID);
                                    }

                                    int firstTime = volDayMsg.getMeasureData().get(0).getStat_Time();
                                    UploadCACData data = new UploadCACData();
                                    data.setMonDataNodeAttr(cacGlobalData.cacDeviceID, Integer.toString(1));
                                    String deviceId = new String(i1Frame.getVoltageMonitorID());
                                    String strMeasurePointNo = Integer.toString(volDayMsg.getMeasure_Point_ID());
                                    String strTimesTamp = new SimpleDateFormat("yyyy-MM-dd").format(new Date((long) firstTime * (long) 1000));

                                    /**
                                     * 检查数据是周期性数据还是召唤数据；
                                     * 周期性数据：加入全局缓存；
                                     * 召唤数据：加入对应指令任务的缓存；
                                     *
                                     * 以下每种帧报文处理类同；
                                     * */

                                    VoltageDayMon_Data item = volDayMsg.getMeasureData().get(0);
                                    data.addAttrNode("DQualifiedrate", Util.rateBytesToValue(item.getDQualified_rate()));
                                    data.addAttrNode("DOvercaprate", Util.rateBytesToValue(item.getDOvercap_rate()));
                                    data.addAttrNode("DUnderlowerrate", Util.rateBytesToValue(item.getDUnderlower_rate()));
                                    data.addAttrNode("DStatisticaltime", Integer.toString(item.getDStatistical_time()));
                                    data.addAttrNode("DQualifiedtime", Integer.toString(item.getDQualified_time()));
                                    data.addAttrNode("DOvercaptime", Integer.toString(item.getDOvercap_time()));
                                    data.addAttrNode("DUnderlowertime", Integer.toString(item.getDUnderlower_time()));
                                    data.addAttrNode("DAveragevalue", Util.voltageBytesToValue(item.getDAverage_value()));
                                    data.addAttrNode("DMinivalue", Util.voltageBytesToValue(item.getDMini_value()));
                                    data.addAttrNode("DMinivaluetime", new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date((long) item.getDMini_value_Time() * (long) 1000)));
                                    data.addAttrNode("DMaxvalue", Util.voltageBytesToValue(item.getDMax_value()));
                                    data.addAttrNode("DMaxvaluetime", new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date((long) item.getDMax_value_time() * (long) 1000)));

                                    Command cmd = device.getCurrentCmd();
                                    if (cmd != null && cmd.getCmd_type().equals("GETDSTATDATA") && cmd.getCmdStatus() == 2) {
                                        data.setDataNodeAttr(deviceId, strMeasurePointNo, "031002", cmd.getCmd_id(), strTimesTamp);
                                        cmd.setCmdResult(data.getMsg());
                                        cmd.setCmdStatus(3);
                                        log.info("{}:  VoltageDayData is buffered ; commandId:{}", deviceID, cmd.getCmd_id());
                                    } else {
                                        data.setDataNodeAttr(deviceId, strMeasurePointNo, "031002", null, strTimesTamp);
                                        cacGlobalData.voltageDayDataXml.add(data.getMsg());
//                                        wsClientFactory.uploadCACData(data.getMsg());
                                    }

                                    log.info(data.getMsg());


                                    //  标记装置的主发状态:关闭（未占用）
                                    device.setDeviceSend(2);

                                    break;
                                }
                                case 0x06:  // 月统计数据报
                                {
                                    log.info("{}: <<< VoltageMonData", deviceID);
                                    //  标记装置的主发状态:打开
                                    device.setDeviceSend(1);

                                    VoltageDayMon_Msg volMonMsg = VoltageDayMon_Msg.decFrameBody(i1Frame.getMsgBody());
                                    log.info("{}: decode volMonMsg", deviceID);
                                    VoltageDayMon_Cfm cfm = new VoltageDayMon_Cfm();
                                    cfm.setMeasure_Point_ID(volMonMsg.getMeasure_Point_ID());
                                    cfm.setData_Status((byte) 0xFF);

                                    ctx.writeAndFlush(FrameFactory.vol_Mon_CfmFrame(i1Frame.getVoltageMonitorID(), i1Frame.getFrameSerialNum(), cfm.toByteBuf()));
                                    log.info("{}: >>> vol_Mon_CfmFrame", deviceID);


                                    if (volMonMsg.getMeasureData_Num() <= 0) {
                                        //  处理数据异常
                                        log.info("err: MeasureData_Num of VoltageMonData ; device:{}", deviceID);
                                    }

                                    int firstTime = volMonMsg.getMeasureData().get(0).getStat_Time();
                                    UploadCACData data = new UploadCACData();
                                    data.setMonDataNodeAttr(cacGlobalData.cacDeviceID, Integer.toString(1));
//                                    String deviceId = new String(i1Frame.getVoltageMonitorID());
                                    String strMeasurePointNo = Integer.toString(volMonMsg.getMeasure_Point_ID());
                                    String strTimesTamp = new SimpleDateFormat("yyyy-MM").format(new Date((long) firstTime * (long) 1000));

                                    /**
                                     * 检查数据是周期性数据还是召唤数据；
                                     * 周期性数据：加入全局缓存；
                                     * 召唤数据：加入对应指令任务的缓存；
                                     *
                                     * 以下每种帧报文处理类同；
                                     * */


                                    VoltageDayMon_Data item = volMonMsg.getMeasureData().get(0);
                                    data.addAttrNode("DQualifiedrate", Util.rateBytesToValue(item.getDQualified_rate()));
                                    data.addAttrNode("DOvercaprate", Util.rateBytesToValue(item.getDOvercap_rate()));
                                    data.addAttrNode("DUnderlowerrate", Util.rateBytesToValue(item.getDUnderlower_rate()));
                                    data.addAttrNode("DStatisticaltime", Integer.toString(item.getDStatistical_time()));
                                    data.addAttrNode("DQualifiedtime", Integer.toString(item.getDQualified_time()));
                                    data.addAttrNode("DOvercaptime", Integer.toString(item.getDOvercap_time()));
                                    data.addAttrNode("DUnderlowertime", Integer.toString(item.getDUnderlower_time()));
                                    data.addAttrNode("DAveragevalue", Util.voltageBytesToValue(item.getDAverage_value()));
                                    data.addAttrNode("DMinivalue", Util.voltageBytesToValue(item.getDMini_value()));
                                    data.addAttrNode("DMinivaluetime", new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date((long) item.getDMini_value_Time() * (long) 1000)));
                                    data.addAttrNode("DMaxvalue", Util.voltageBytesToValue(item.getDMax_value()));
                                    data.addAttrNode("DMaxvaluetime", new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date((long) item.getDMax_value_time() * (long) 1000)));

                                    Command cmd = device.getCurrentCmd();
                                    if (cmd != null && cmd.getCmd_type().equals("GETMSTATDATA") && cmd.getCmdStatus() == 2) {
                                        data.setDataNodeAttr(deviceID, strMeasurePointNo, "031003", cmd.getCmd_id(), strTimesTamp);
                                        cmd.setCmdResult(data.getMsg());
                                        cmd.setCmdStatus(3);
                                        log.info("{}: buffer VoltageMonData", deviceID);
                                    } else {
                                        data.setDataNodeAttr(deviceID, strMeasurePointNo, "031003", null, strTimesTamp);
                                        cacGlobalData.voltageMonDataXml.add(data.getMsg());
                                    }

                                    log.info(data.getMsg());


                                    //  标记装置的主发状态:关闭（未占用）
                                    device.setDeviceSend(2);

                                    break;
                                }
                                default:
                                    log.error("err: VoltageMonData ; device:{}", deviceID);
                            }
                            break;
                        }
                        case 0x06:    // 数据请求确认报文（CAC -> 主发）
                        {
                            if (i1Frame.getMsgType() == 0xA1) {
                                log.info("{}: <<< RequestVoltageData ConfirmFrame", deviceID);

                                //  标记 指令下发通道状态
                                device.setCacSend(2);

                                //  查找对应指令，并标记指令执行阶段
                                Command cmd = device.getCurrentCmd();
                                String cmdType = cmd.getCmd_type();
                                if (cmdType != null && cmdType.equals("GETDATA") || cmdType.equals("GETDSTATDATA") || cmdType.equals("GETMSTATDATA")) {
                                    cmd.setCmdStatus(2);
                                    cmd.setTimeOut(0);
                                } else {
                                    log.info("err: command is not exist ; device:{}", deviceID);
                                }
                            } else {
                                log.info("err: MsgType of RequestVoltageData ConfirmFrame ; device:{}", deviceID);
                            }
                            break;
                        }
                        case 0x08:    // 配置/状态交互响应报文（CAC -> 主发）
                        {
                            //  标记 指令下发通道占用状态
                            device.setCacSend(2);

                            switch (i1Frame.getMsgType()) {
                                case 0xA4:  // 装置时间查询/设置
                                {
                                    log.info("{}: <<< ClocktimeStamp-Frame", deviceID);
                                    Cfg_Time_Cfm cfgTimeCfm = Cfg_Time_Cfm.decFrameBody(i1Frame.getMsgBody());
                                    if (cfgTimeCfm.getCommand_Status() == 0xFF) {
                                        Command cmd = device.getCurrentCmd();
                                        if (cmd != null && cmd.getCmd_type().equals("GETCONFIG") && cmd.getAction().equals("ClocktimeStamp")) {
                                            String value = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date((long) cfgTimeCfm.getClocktime_Stamp() * (long) 1000));
                                            UploadCACConfig result = new UploadCACConfig();
                                            result.setConfigNodeAttr(device.getClientId(), "0", cmd.getCmd_id());
                                            result.addAttrNode(cmd.getAction(), value);
                                            cmd.setCmdResult(result.getMsg());

                                            log.info(result.getMsg());

                                            //  标记指令的生命周期阶段
                                            cmd.setCmdStatus(3);
                                            cmd.setTimeOut(0);
                                        } else {
                                            log.info("err: GETCONFIG-ClocktimeStamp-Frame Command is not exist ; device:{}", deviceID);
                                        }
                                    }
                                    break;
                                }
                                case 0xA6:  // 装置通信参数查询/设置
                                {
                                    log.info("{}: <<< Device Communication ConfigFrame", deviceID);

                                    Cfg_CommArg_Cfm cfgCommArgCfm = Cfg_CommArg_Cfm.decFrameBody(i1Frame.getMsgBody());

                                    int flag = cfgCommArgCfm.getRequest_Flag();
                                    String action = null;
                                    if (flag == 0x02) {
                                        action = "APN";
                                    } else if (flag == 0x10) {
                                        action = "Heartbeatcycle";
                                    } else if (flag == 0x20) {
                                        action = "MessageCentor";
                                    }
                                    Command cmd = device.getCurrentCmd();
                                    if (cmd != null && cmd.getCmd_type().equals("GETCONFIG") && cmd.getAction().equals(action)) {
                                        String attrValue = null;
                                        if (flag == 0x02) {
                                            attrValue = cfgCommArgCfm.getAPN();
                                        } else if (flag == 0x10) {
                                            attrValue = Integer.toString(cfgCommArgCfm.getHeart_Beat_Cycle());
                                        } else if (flag == 0x20) {
                                            attrValue = cfgCommArgCfm.getMessage_Centor();
                                        }
                                        UploadCACConfig result = new UploadCACConfig();
                                        result.setConfigNodeAttr(device.getClientId(), "0", cmd.getCmd_id());
                                        result.addAttrNode(action, attrValue);
                                        cmd.setCmdResult(result.getMsg());

                                        log.info(result.getMsg());

                                        //  标记指令的生命周期阶段
                                        cmd.setCmdStatus(3);
                                        cmd.setTimeOut(0);
                                    } else {
                                        log.info("err: command (GETCONFIG:{}) is not exist ; device:{}", action, deviceID);
                                    }
                                    break;
                                }
                                case 0xA7:  // 监测点参数查询/设置
                                {
                                    log.info("{}: <<< cfgMPArgCfm", deviceID);

                                    Cfg_MPArg_Cfm cfgMPArgCfm = Cfg_MPArg_Cfm.decFrameBody(i1Frame.getMsgBody());

                                    int flag = cfgMPArgCfm.getRequest_Flag();
                                    String action = null;
                                    if (flag == 0x0001) {
                                        action = "MINTimeStamp";
                                    } else if (flag == 0x0004) {
                                        action = "ULValue";
                                    } else if (flag == 0x0008) {
                                        action = "LLValue";
                                    } else if (flag == 0x0010) {
                                        action = "SettleDate";
                                    } else if (flag == 0x0020) {
                                        action = "VoltageLevel";
                                    }
                                    Command currCmd = device.getCurrentCmd();
                                    if (currCmd != null && currCmd.getCmd_type().equals("GETCONFIG") && currCmd.getAction().equals(action)) {
                                        String attrValue = null;
                                        if (flag == 0x0001) {
                                            attrValue = Integer.toString(cfgMPArgCfm.getMIN_Time_Cycle());
                                        } else if (flag == 0x0004) {
                                            attrValue = cfgMPArgCfm.getUL_Value();
                                        } else if (flag == 0x0008) {
                                            attrValue = cfgMPArgCfm.getLL_Value();
                                        } else if (flag == 0x0010) {
                                            attrValue = cfgMPArgCfm.getSettle_Date();
                                        } else if (flag == 0x0020) {
                                            attrValue = cfgMPArgCfm.getVoltage_Level();
                                        }

                                        UploadCACConfig result = new UploadCACConfig();
                                        result.setConfigNodeAttr(device.getClientId(), Integer.toString(cfgMPArgCfm.getMeasure_Point_ID()), currCmd.getCmd_id());
                                        result.addAttrNode(action, attrValue);

                                        currCmd.setCmdResult(result.getMsg());

                                        log.info(result.getMsg());

                                        //  标记指令的生命周期阶段
                                        currCmd.setCmdStatus(3);
                                        currCmd.setTimeOut(0);
                                    } else{
                                        log.info("err: Command(GETCONFIG:{}) is not exist ; device:{}", action, deviceID);
                                    }
                                    break;
                                }
                                case 0xA8:  // 装置事件参数查询/设置
                                {
                                    log.info("{}: <<< cfgMeasureArgCfm Frame", deviceID);

                                    Cfg_MeasureArg_Cfm cfgMeasureArgCfm = Cfg_MeasureArg_Cfm.decFrameBody(i1Frame.getMsgBody());

                                    break;
                                }
                                case 0xA9:  // 装置所属CAC的信息查询/设置
                                {
                                    log.info("{}: <<< cfgCACSubCfm Frame", deviceID);

                                    Cfg_CACSub_Cfm cfgCACSubCfm = Cfg_CACSub_Cfm.decFrameBody(i1Frame.getMsgBody());

                                    if (cfgCACSubCfm.getCommand_Status() == 0x00) {
                                        // handle err
                                        log.warn("err: Command_Status of cfgCACSubCfm ; device:{}", deviceID);
                                    }

                                    int flag = cfgCACSubCfm.getRequest_Flag();
                                    String action = null;
                                    if (flag == 0x01) {
                                        action = "CACIP";
                                    } else if (flag == 0x04) {
                                        action = "CACPhoneNumber";
                                    }
                                    Command currCmd = device.getCurrentCmd();
                                    if (currCmd != null && currCmd.getCmd_type().equals("GETCONFIG") && currCmd.getAction().equals(action)) {
                                        String attrValue = null;
                                        if (flag == 0x01) {
                                            attrValue = cfgCACSubCfm.getCAC_IP();
                                        } else if (flag == 0x04) {
                                            attrValue = cfgCACSubCfm.getCall_Centor();
                                        }

                                        UploadCACConfig result = new UploadCACConfig();
                                        result.setConfigNodeAttr(device.getClientId(), "0", currCmd.getCmd_id());
                                        result.addAttrNode(action, attrValue);

                                        currCmd.setCmdResult(result.getMsg());

                                        log.info(result.getMsg());

                                        //  标记指令的生命周期阶段
                                        currCmd.setCmdStatus(3);
                                        currCmd.setTimeOut(0);
                                    }else{
                                        log.info("err: Command(GETCONFIG:{}) is not exist ; device:{}", action, deviceID);
                                    }
                                    break;
                                }
                                case 0xAA:  // 装置基本信息查询
                                {
                                    log.info("{}: <<< cfgBaseInfoCfm Frame", deviceID);

                                    Cfg_BaseInfo_Cfm cfgBaseInfoCfm = Cfg_BaseInfo_Cfm.decFrameBody(i1Frame.getMsgBody());


                                    Command cmd = device.getCurrentCmd();

                                    if (cmd == null) {
                                        log.info("err: Command(GETCONFIG:cfgBaseInfoCfm) is not exist ; device:{}", deviceID);
                                    } else {
                                        UploadCACConfig result = new UploadCACConfig();
                                        result.setConfigNodeAttr(device.getClientId(), "0", cmd.getCmd_id());
                                        String ac = cmd.getAction();
                                        switch (ac) {
                                            case "VMDModel":
                                                result.addAttrNode(cmd.getAction(), cfgBaseInfoCfm.getVMD_Model());
                                                break;
                                            case "SoftwareVersion":
                                                result.addAttrNode(cmd.getAction(), cfgBaseInfoCfm.getSoftware_Version());
                                                break;
                                            case "HardwareVersion":
                                                result.addAttrNode(cmd.getAction(), cfgBaseInfoCfm.getHardware_Version());
                                                break;
                                            case "ProtocolVersion":
                                                result.addAttrNode(cmd.getAction(), cfgBaseInfoCfm.getProtocol_Version());
                                                break;
                                            case "BsManufacturer":
                                                result.addAttrNode(cmd.getAction(), cfgBaseInfoCfm.getBs_Manufacturer());
                                                break;
                                            case "BsProductionDate":
                                                result.addAttrNode(cmd.getAction(), cfgBaseInfoCfm.getBs_Production_Date());
                                                break;
                                            case "VMDPhoneNumber":
                                                result.addAttrNode(cmd.getAction(), cfgBaseInfoCfm.getVMD_Phone_Number());
                                                break;
                                            case "VMDCardNumber":
                                                result.addAttrNode(cmd.getAction(), cfgBaseInfoCfm.getVMD_IMSI_Number());
                                        }
                                        cmd.setCmdResult(result.getMsg());

                                        log.info(result.getMsg());

                                        //  标记指令的生命周期阶段
                                        cmd.setCmdStatus(3);
                                        cmd.setTimeOut(0);
                                    }

                                    break;
                                }
                                case 0xAB:  // 装置工作状态信息查询
                                {
                                    log.info("{}: <<< cfgStatusCfm Frame", deviceID);

                                    Cfg_Status_Cfm cfgStatusCfm = Cfg_Status_Cfm.decFrameBody(i1Frame.getMsgBody());
                                    Command cmd = device.getCurrentCmd();
                                    if (cmd == null) {
                                        log.info("err: Command(GETCONFIG:WorkingTime or TotalWorkingTime) is not exist ; device:{}", deviceID);
                                        break;
                                    }
                                    if (cmd.getCmd_type().equals("GETCONFIG") && cmd.getAction().equals("WorkingTime")) {
                                        UploadCACConfig result = new UploadCACConfig();
                                        result.setConfigNodeAttr(device.getClientId(), "0", cmd.getCmd_id());
                                        result.addAttrNode("WorkingTime", Integer.toString(cfgStatusCfm.getWorking_Time()));

                                        cmd.setCmdResult(result.getMsg());

                                        log.info(result.getMsg());

                                        //  标记指令的生命周期阶段
                                        cmd.setCmdStatus(3);
                                        cmd.setTimeOut(0);

                                        break;
                                    }
                                    if (cmd.getCmd_type().equals("GETCONFIG") && cmd.getAction().equals("TotalWorkingTime")){
                                        UploadCACConfig result = new UploadCACConfig();
                                        result.setConfigNodeAttr(device.getClientId(), "0", cmd.getCmd_id());
                                        result.addAttrNode("TotalWorkingTime", Integer.toString(cfgStatusCfm.getWorking_Time()));
                                        cmd.setCmdResult(result.getMsg());

                                        log.info(result.getMsg());

                                        //  标记指令的生命周期阶段
                                        cmd.setCmdStatus(3);
                                        cmd.setTimeOut(0);

                                        break;
                                    }

                                    break;
                                }
                                case 0xAC:  // 装置通信流量信息查询
                                {
                                    log.info("{}: <<< cfgFlowCfm Frame", deviceID);

                                    Cfg_Flow_Cfm cfgFlowCfm = Cfg_Flow_Cfm.decFrameBody(i1Frame.getMsgBody());
                                    Command cmd = device.getCurrentCmd();
                                    if (cmd == null) {
                                        log.info("err: Command(GETCONFIG:SendFlow/RecevieFlow) is not exist ; device:{}", deviceID);
                                    }

                                    if (cmd.getCmd_type().equals("GETCONFIG") && cmd.getAction().equals("RecevieFlow")) {
                                        UploadCACConfig result = new UploadCACConfig();
                                        result.setConfigNodeAttr(device.getClientId(), "0", cmd.getCmd_id());
                                        result.addAttrNode("RecevieFlow", Integer.toString(cfgFlowCfm.getItems().get(0).getReceive_Flow()));

                                        cmd.setCmdResult(result.getMsg());

                                        log.info(result.getMsg());

                                        //  标记指令的生命周期阶段
                                        cmd.setCmdStatus(3);
                                        cmd.setTimeOut(0);

                                    }
                                    if (cmd.getCmd_type().equals("GETCONFIG") && cmd.getAction().equals("SendFlow")){
                                        UploadCACConfig result = new UploadCACConfig();
                                        result.setConfigNodeAttr(device.getClientId(), "0", cmd.getCmd_id());
                                        result.addAttrNode("SendFlow", Integer.toString(cfgFlowCfm.getItems().get(0).getSend_Flow()));
                                        cmd.setCmdResult(result.getMsg());

                                        log.info(result.getMsg());

                                        //  标记指令的生命周期阶段
                                        cmd.setCmdStatus(3);
                                        cmd.setTimeOut(0);
                                    }

                                    break;
                                }
                                case 0xAD:  // 装置ID查询/设置
                                {
                                    log.info("{}: <<< cfgIdCfg Frame", deviceID);

                                    Cfg_ID_Cfm cfgIdCfg = Cfg_ID_Cfm.decFrameBody(i1Frame.getMsgBody());

                                    Command cmd = device.getCurrentCmd();
                                    if (cmd == null) {
                                        log.info("err: Command(GETCONFIG:BsIdentifier/VMDID) is not exist ; device:{}", deviceID);
                                    }
                                    if (cmd.getCmd_type().equals("GETCONFIG") && cmd.getAction().equals("BsIdentifier")) {
                                        UploadCACConfig result = new UploadCACConfig();
                                        result.setConfigNodeAttr(device.getClientId(), "0", cmd.getCmd_id());
                                        result.addAttrNode("BsIdentifier", cfgIdCfg.getOriginal_ID());
                                        cmd.setCmdResult(result.getMsg());

                                        log.info(result.getMsg());

                                        //  标记指令的生命周期阶段
                                        cmd.setCmdStatus(3);
                                        cmd.setTimeOut(0);
                                    }
                                    if (cmd.getCmd_type().equals("GETCONFIG") && cmd.getAction().equals("VMDID")) {
                                        UploadCACConfig result = new UploadCACConfig();
                                        result.setConfigNodeAttr(device.getClientId(), "0", cmd.getCmd_id());
                                        result.addAttrNode("VMDID", cfgIdCfg.getOriginal_ID());

                                        cmd.setCmdResult(result.getMsg());

                                        log.info(result.getMsg());

                                        //  标记指令的生命周期阶段
                                        cmd.setCmdStatus(3);
                                        cmd.setTimeOut(0);
                                    }

                                    if (cmd.getCmd_type().equals("SETCONFIG") && cmd.getAction().equals("VMDID")) {
                                        log.info("--------------->>>>>:frameID:{},isOK:{}",new java.lang.String(i1Frame.getVoltageMonitorID()),cfgIdCfg.getCommand_Status());
//                                        log.info();
                                        cacGlobalData.getDeviceMap4Device().remove(device.getClientId());
                                        device.setClientId(new String(i1Frame.getVoltageMonitorID()));
                                        cacGlobalData.getDeviceMap4Device().put(device.getClientId(), device);

                                        UploadCtrlResult ctrlResult = new UploadCtrlResult();
                                        ctrlResult.setResultNodeAttr(cmd.getCmd_id(),"0");
                                        cmd.setCmdResult(ctrlResult.getMsg());

                                        log.info(ctrlResult.getMsg());

                                        //  标记指令的生命周期阶段
                                        cmd.setCmdStatus(3);
                                        cmd.setTimeOut(0);
                                    }

                                    break;
                                }
                                case 0xAE:  // 装置复位
                                {
                                    log.info("{}: <<< cfgResetCfm Frame", deviceID);

                                    Cfg_Reset_Cfm cfgResetCfm = Cfg_Reset_Cfm.decFrameBody(i1Frame.getMsgBody());
                                    break;
                                }
                                case 0xAF:  // 装置调试命令交互
                                {
                                    log.info("{}: <<< cfgDebug Frame", deviceID);

                                    Cfg_DebugDownload_Cfm cfgDebug = Cfg_DebugDownload_Cfm.decFrameBody(i1Frame.getMsgBody());
                                    break;
                                }
                                default:
                                    log.error("err: cfg Frame ; device:{}", deviceID);
                            }
                            break;
                        }
                        case 0x09:    // 流量数据报文（电压监测仪 -> 主发）
                        {
                            log.info("{}: <<< flowData Frame", deviceID);
                            //  标记装置的主发状态:打开
                            device.setDeviceSend(1);

                            FlowData_Msg flowData = FlowData_Msg.decFrameBody(i1Frame.getMsgBody());

                            FlowData_Cfm flowData_cfm = new FlowData_Cfm();
                            flowData_cfm.setCommand_Status((byte) 0xFF);
                            ctx.writeAndFlush(FrameFactory.flow_CfmFrame(i1Frame.getVoltageMonitorID(), i1Frame.getFrameSerialNum(), flowData_cfm.toByteBuf()));
                            log.info("{}: >>> flowData ConfirmFrame", deviceID);


                            //  标记装置的主发状态:关闭（未占用）
                            device.setDeviceSend(2);
                            break;
                        }
                        case 0x11:    // 事件信息报文（电压监测仪 -> 主发）
                        {
                            log.info("{}: <<< eventUploadMsg Frame", deviceID);
                            //  标记装置的主发状态:打开
                            device.setDeviceSend(1);

                            EventUpload_Msg eventUploadMsg = EventUpload_Msg.decFrameBody(i1Frame.getMsgBody());

                            //  发送响应帧
                            EventUpload_Cfm eventUpload_cfm = new EventUpload_Cfm();
                            eventUpload_cfm.setMeasure_Point_ID(eventUploadMsg.getMeasure_Point_ID());
                            eventUpload_cfm.setCommand_Status((byte) 0xFF);
                            ctx.writeAndFlush(FrameFactory.event_CfmFrame(i1Frame.getVoltageMonitorID(), i1Frame.getFrameSerialNum(), eventUpload_cfm.toByteBuf()));
                            log.info(" {}: >>> eventData ConfirmFrame", deviceID);

                            UploadCACData data = new UploadCACData();
                            data.setMonDataNodeAttr(cacGlobalData.cacDeviceID, Integer.toString(1));
                            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
                            String t = sf.format(new Date((long) (eventUploadMsg.getStatTime()) * (long) 1000));
                            data.setDataNodeAttr(new String(i1Frame.getVoltageMonitorID()), Integer.toString(eventUploadMsg.getMeasure_Point_ID()), "031004", null, t);
                            String attrValue = null;
                            if (eventUploadMsg.getFault_Type() == 0x01) {
                                attrValue = "停电";
                            } else if (eventUploadMsg.getFault_Type() == 0x02) {
                                attrValue = "上电";
                            } else if (eventUploadMsg.getFault_Type() == 0x03) {
                                attrValue = "越上限";
                            } else if (eventUploadMsg.getFault_Type() == 0x04) {
                                attrValue = "越上限恢复";
                            } else if (eventUploadMsg.getFault_Type() == 0x05) {
                                attrValue = "越下限";
                            } else if (eventUploadMsg.getFault_Type() == 0x06) {
                                attrValue = "越下限恢复";
                            } else if (eventUploadMsg.getFault_Type() == 0x07) {
                                attrValue = "复位";
                            } else if (eventUploadMsg.getFault_Type() == 0x08) {
                                attrValue = "其他";
                            }
                            data.addAttrNode("EventType", attrValue);

                            cacGlobalData.eventDataXml.add(data.getMsg());

                            log.info(data.getMsg());

                            //  标记装置的主发状态:关闭（未占用）
                            device.setDeviceSend(2);

                            break;
                        }
                        case 0x14:    // 远程升级数据报文（CAC -> 主发）
                        {
                            switch (i1Frame.getMsgType()) {
                                case 0xC7: {
                                    log.info("{}: <<< upgradeStartCfm Frame", deviceID);

                                    Upgrade_Start_Cfm upgradeStartCfm = Upgrade_Start_Cfm.decFrameBody(i1Frame.getMsgBody());
                                    break;
                                }
                                case 0xC8: {
                                    log.info("{}: <<< upgradeProcCfm Frame", deviceID);
                                    log.info(new String(i1Frame.getVoltageMonitorID()));

                                    Upgrade_Proc_Cfm upgradeProcCfm = Upgrade_Proc_Cfm.decFrameBody(i1Frame.getMsgBody());
                                    break;
                                }
                                case 0xC9: {
                                    log.info("{}: <<< upgradeEndCfm Frame", deviceID);
                                    log.info(new String(i1Frame.getVoltageMonitorID()));

                                    Upgrade_End_Cfm upgradeEndCfm = Upgrade_End_Cfm.decFrameBody(i1Frame.getMsgBody());
                                    break;
                                }
                                default:
                                    log.debug("err: upgrade Frame ; device:{}", deviceID);
                            }

                            break;
                        }
                        default:
                            log.debug("err: type of frame： " + i1Frame.getFrameType());
                    }

                } catch (Exception e) {
                    log.error("handle frameMessage error!!", e);
                }
            }
        });
    }

    //  任务三、执行发送 ‘缓存的电压数据（发送电压数据、事件信息、流量信息等）’ 到CAG；
    public void executeUploadCACData() {
        pools.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    //  电压分钟平均数据
                    Iterator iterator = cacGlobalData.voltageDataXml.iterator();
                    while (iterator.hasNext()) {
                        String xml = (String) iterator.next();

                        if (cagOnline) {
                            Object[] objects = client.invoke("uploadCACData", xml);
                            log.info("<<< voltageMinDataXml confirmMsg from CAG:{}",objects);
                        }
                        //  移除缓存的数据
                        cacGlobalData.voltageDataXml.remove(xml);
                    }

                    //  电压日统计数据
                    Iterator iteratorDay = cacGlobalData.voltageDayDataXml.iterator();
                    while (iteratorDay.hasNext()) {
                        String xmlDay = (String) iteratorDay.next();
                        if (cagOnline) {
                            Object[] objects = client.invoke("uploadCACData", xmlDay);
                            log.info("<<< voltageDayDataXml confirmMsg from CAG:{}",objects);
                        }
                        //  移除缓存的数据
                        cacGlobalData.voltageDayDataXml.remove(xmlDay);
                    }

                    //  电压月统计数据
                    Iterator iteratorMon = cacGlobalData.voltageMonDataXml.iterator();
                    while (iteratorMon.hasNext()) {
                        String xmlMon = (String) iteratorMon.next();

                        if (cagOnline) {
                            Object[] objects = client.invoke("uploadCACData", xmlMon);
                            log.info("<<< voltageMonDataXml confirmMsg from CAG:{}",objects);
                        }
                        //  移除缓存的数据
                        cacGlobalData.voltageMonDataXml.remove(xmlMon);
                    }

                } catch (Exception e) {
                    log.error("uploadCACData throw Exception:{}",e.toString());
                    cagOnline = false;
                    if (client != null) {
                        client.destroy();
                    }
                }

            }
        });
    }

    //  任务四：使用线程池资源上传CAC和电压监测装置的心跳信息
    public void uploadCACHeartbeatInfo() {
        pools.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    String curtime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(System.currentTimeMillis()));
                    HeartBeatXmlMsg heartBeatXmlMsg = new HeartBeatXmlMsg();
                    heartBeatXmlMsg.setCacNodeAttr(cacGlobalData.cacDeviceID, cacGlobalData.cacIP, curtime, cacGlobalData.cacTemperature);

                    Iterator iterator = cacGlobalData.deviceMap4Device.entrySet().iterator();
                    while (iterator.hasNext()) {
                        Map.Entry entry = (Map.Entry) iterator.next();
                        String device_id = (String) entry.getKey();
                        Device device = (Device) entry.getValue();
                        Element dev = new Element("device");
                        dev.setAttribute("id", device_id);
                        if (device.getChannelId() != null) {
                            heartBeatXmlMsg.addDeviceNode(device_id, "NORMAL");
                        } else {
                            heartBeatXmlMsg.addDeviceNode(device_id, "BREAK");
                        }
                    }

                    // 创建动态客户端
                    String params = heartBeatXmlMsg.getMsg();

                    log.info(">>> uploadCACHeartBeatInfo to CAG:{}",params);

                    if (!cagOnline) {
                        log.warn("CAG is not online !!! Can Not uploadCACHeartBeatInfo ...");
                        return;
                    }

//                    Object[] objects = wsClientFactory.uploadHeartbeatInfo(params);
                    Object[] objects = client.invoke("uploadCACHeartbeatInfo", params);
                    log.info("<<< uploadCACHeartbeatInfo confirmMsg from CAG：{}", objects);
                } catch (RuntimeException e) {
                    log.error("result:uploadCACHeartbeatInfo:RuntimeException:{}", e.toString());
                    cagOnline = false;
                    if (client != null) {
                        log.info("RuntimeException: client.destroy()");
                        client.destroy();
                    }
                } catch (Exception e) {
                    log.error("result:uploadCACHeartbeatInfo:Exception:",e);
                    cagOnline = false;
                    if (client != null) {
                        log.info("Exception: client.destroy()");
                        client.destroy();
                    }
                }
            }
        });

    }

    /**
     * 任务：遍历每个装置设备缓存的待下发的指令,发送到对应的装置上并检查
     * 已下发指令的确认帧是否超时；同时将装置执行完指令并已返回的结果 上送到CAG.
     */
    public void sendCmdResult() {
        pools.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Iterator iterator = cacGlobalData.deviceMap4Device.entrySet().iterator();
                    long currTime = System.currentTimeMillis() / 1000;
                    while (iterator.hasNext()) {
                        Map.Entry entry = (Map.Entry) iterator.next();
                        String device_id = (String) entry.getKey();
                        Device device = (Device) entry.getValue();

                        //  1.如果设备是否在线，如果离线，则不在检查超时/指令等信息
                        if (device.getChannelId() == null) {
                            continue;
                        }

                        //  2.检查心跳超时
                        int idleTimeOutNum = device.getIdleTimeOutNumber();
                        long idleTimeOut = currTime - device.getLastHeartBeatTime() / 1000;
                        long idleTime = device.getHeatBeatIdleTime();
                        if (idleTimeOut >= idleTime) {          //  如果超时
                            long c1 = idleTimeOut / idleTime;   //  超时次数
                            if (c1 > idleTimeOutNum) {          //  如果新增一次超时
                                int c2 = idleTimeOutNum + 1;
                                device.setIdleTimeOutNumber(c2);    //  更新最新的超时次数
                                log.info("{}: heartBeatTimeOutCount: {}.", device_id, c2);
                                log.warn("{}: systemTime:{}s,lastHeartBeatTime:{}s; idleTimeOut:{}s;defaultHeatBeatIdleTime:{}s", device_id, currTime, device.getLastHeartBeatTime() / 1000, idleTimeOut, device.getHeatBeatIdleTime());
                                if (c2 >= 3) {
                                    //  处理3次超时，标记设备离线
                                    log.info("{}: is marked outlive !", device_id);
                                    CACGlobalData.channelGroup.find(device.getChannelId()).close();
                                    device.setChannelId(null);
                                    //  清空指令
                                    device.getCagCmdList().clear();
                                    device.setCurrentCmd(null);
                                }
                            }
                        }

                        //  3.检查接收的指令

//                        ConcurrentLinkedQueue<Command> cmdList = device.getCagCmdList();
                        //  检查是否有指令
                        if (device.getCurrentCmd() == null) {
                            device.setCurrentCmd(device.getCagCmdList().poll());
                        }
                        if (device.getCurrentCmd() == null) {
                            continue;
                        }

                        int size = device.getCagCmdList().size();
                        if (size > 0) {
                            log.info("{}: Command Count：{}", device_id, size);
                        }

                        Command currCmd = device.getCurrentCmd();


                        int cmdStatus = currCmd.getCmdStatus();
                        ChannelId channelId = device.getChannelId();

                        ByteBuf bf = currCmd.getCmdFrame();
                        if (bf == null) {
                            log.info("error:command frame is null!!");
                            device.setCurrentCmd(device.getCagCmdList().poll());
                            continue;
                        }


                        if (cmdStatus == 0) {   //  指令待发出
                            if (channelId != null) {    //  装置设备在线
                                device.setCacSend(1);   //  标记打开(占用)下发通道

                                byte[] wd = new byte[bf.writerIndex() - bf.readerIndex()];
                                bf.getBytes(bf.readerIndex(), wd);

                                log.info("{}: command frame >>> :{}", device_id, Arrays16.toString(wd));
                                bf.retain();
                                CACGlobalData.channelGroup.find(channelId).writeAndFlush(bf);
                                log.info("ref: >>> :{}",bf.refCnt());
                                currCmd.setCmdStatus(1);      //  设置指令状态
                                currCmd.setTimeOut(0);
                            }

                        } else if (cmdStatus == 1) {      // 检查超时
                            currCmd.addTimeOut(2);
                            int timeOut = currCmd.getTimeOut();
                            if (30 == timeOut) {             //  指令确认帧 第一次超时
                                log.info("{}:cmdStatus:1, cmdType:{} timeOut: 30 seconds, cmdId:{},", device_id, currCmd.getCmd_type(), currCmd.getCmd_id());
                                bf.retain();
                                CACGlobalData.channelGroup.find(channelId).writeAndFlush(bf);
                                log.info("ref: >>> :{}",bf.refCnt());
                            } else if (60 == timeOut) {      //  指令确认帧 第二次超时
                                log.info("{}:cmdStatus:1, cmdType:{} timeOut: 60 seconds, cmdId:{},", device_id, currCmd.getCmd_type(), currCmd.getCmd_id());
                                bf.retain();
                                CACGlobalData.channelGroup.find(channelId).writeAndFlush(bf);
                                log.info("ref: >>> :{}",bf.refCnt());
                            } else if (90 == timeOut) {                     //  指令确认帧 第三次超时
                                log.info("{}:cmdStatus:1, cmdType:{} timeOut: 90 seconds, cmdId:{},", device_id, currCmd.getCmd_type(), currCmd.getCmd_id());
                                //  检查返回结果 是否删除已完成的指令
                                device.setCurrentCmd(device.getCagCmdList().poll());
                            }
                        } else if (cmdStatus == 2) {
                            currCmd.addTimeOut(2);
                            int timeOut = currCmd.getTimeOut();
                            if (30 == timeOut) {             //     第一次超时
                                log.info("{}:cmdStatus:2, cmdType:{} timeOut: 30 seconds, cmdId:{},", device_id, currCmd.getCmd_type(), currCmd.getCmd_id());
                            } else if (60 == timeOut) {      //     第二次超时
                                log.info("{}:cmdStatus:2, cmdType:{} timeOut: 60 seconds, cmdId:{},", device_id, currCmd.getCmd_type(), currCmd.getCmd_id());
                            } else if (90 == timeOut) {      //     第三次超时
                                log.info("{}:cmdStatus:2, cmdType:{} timeOut: 90 seconds, cmdId:{},", device_id, currCmd.getCmd_type(), currCmd.getCmd_id());
                                //  检查返回结果 是否删除已完成的指令
                                device.setCurrentCmd(device.getCagCmdList().poll());
                            }
                        } else if (cmdStatus == 3) {                 //  装置执行指令 结果返回之后
                            try {
                                if (cagOnline) {
                                    Object[] objects;
                                    if (currCmd.getCmd_type().equals("GETCONFIG")) {
                                        objects = client.invoke("uploadCACConfig", currCmd.getCmdResult());
                                        log.info("<<< uploadCACConfig confirmMsg from CAG:{}", objects);
                                    } else if (currCmd.getCmd_type().equals("SETCONFIG")) {
                                        objects = client.invoke("uploadCtrlResult", currCmd.getCmdResult());
                                        log.info("<<< uploadCtrlResult confirmMsg from CAG:{}", objects);
                                    } else {
                                        objects = client.invoke("uploadCACData", currCmd.getCmdResult());
                                        log.info("<<< uploadCACData confirmMsg from CAG:{}", objects);
                                    }
                                }
                                //  检查返回结果 是否删除已完成的指令
                                device.setCurrentCmd(device.getCagCmdList().poll());
                            } catch (Exception e) {
                                log.error(">>> uploadCACData throw Exception:",e);
                                cagOnline = false;
                                if (client != null) {
                                    client.destroy();
                                }
                            }
                        }
                    }
                } catch (Exception e) {
                    log.error("sendCmdResult:Exception:",e);

                }

            }
        });
    }

    //  下发指令
    public void downloadCAGCtrlHandle(String strXMLParams) {
        pools.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    downloadCAGCtrl.parseCAGCtrlMsg(strXMLParams);
                } catch (Exception e) {
                    log.error("downloadCAGCtrlHandle Exception:", e);
                }
            }
        });
    }

    public void creatCAGWSClient() {
        pools.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    if (!cagOnline) {
                        log.warn("CAG is not online!!  creating client .....");
                        if (flag) {
                            return;
                        }
                        // 创建动态客户端
                        flag = true;
                        log.info("flag is opened.");
                        JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
                        log.info("createStartTime(Millis):{}",System.currentTimeMillis());
                        client = dcf.createClient(cagWsUrl);
                        log.info("createEndTime(Millis):{}",System.currentTimeMillis());

                        // 设置超时单位为毫秒
                        HTTPConduit conduit = (HTTPConduit)client.getConduit();
                        HTTPClientPolicy policy = new HTTPClientPolicy();
                        policy.setConnectionTimeout(15000);
                        policy.setAllowChunking(false);
                        policy.setReceiveTimeout(30000);
                        conduit.setClient(policy);


                        cagOnline = true;
                        flag = false;
                        log.info("flag is closed.");
                    }
                } catch (Exception e) {
                    log.info("creatCAGWSClient Exception: {}!!", e.toString());
                    cagOnline = false;
                    flag = false;
                    if (client != null) {
                        client.destroy();
                    }
                }
            }
        });
    }

}
